package com.kldy8.kldyw.live;


import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;


import com.kldy8.kldyw.R;
import com.underconverbg.livedemo.AlertDialogFragment;
import com.underconverbg.livedemo.SrsEncoder;
import com.underconverbg.livedemo.SrsFlvMuxer;
import com.underconverbg.livedemo.SrsMp4Muxer;
import com.underconverbg.livedemo.rtmp.RtmpPublisher;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class LiveAnchorActivity extends Activity implements SurfaceHolder.Callback, Camera.PreviewCallback , AlertDialogFragment.DialogFragmentClickImpl {
    private static final String TAG = "Yasea";
    private ArrayList<String> adapterData ;
    //    Button btnPublish = null;
    boolean isEditStat = false;
    boolean publish = false;
    Button btnSwitch = null;
    Button btnRecord = null;
    Button btnTalk =null;
    Button makesure = null;

    AutoCompleteTextView talk_edit = null;
    LinearLayout hini_send_ly = null;
    EditText efu = null;

    private AudioRecord mic = null;
    private boolean aloop = false;
    private Thread aworker = null;


    private SurfaceView mCameraView = null;
    private Camera mCamera = null;
    private ListView msg_list_view = null;

    private WebView webView = null;


    ArrayAdapter msgAdapter = null;

    private int mPreviewRotation = 90;
    private int mCamId = Camera.getNumberOfCameras() - 1; // default camera
    private byte[] mYuvFrameBuffer = new byte[SrsEncoder.VPREV_WIDTH * SrsEncoder.VPREV_HEIGHT * 3 / 2];

    private String mNotifyMsg;
    private SharedPreferences sp;
    //    private String rtmpUrl = "rtmp://ossrs.net/" + getRandomAlphaString(3) + '/' + getRandomAlphaDigitString(5);
    private String rtmpUrl = "rtmp://120.24.45.154:1935/live...vhost...players/demo.testmingshao";
    private String recPath = Environment.getExternalStorageDirectory().getPath() + "/test.mp4";

    private SrsFlvMuxer flvMuxer = new SrsFlvMuxer(new RtmpPublisher.EventHandler() {
        @Override
        public void onRtmpConnecting(String msg) {
            mNotifyMsg = msg;
            runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onRtmpConnected(String msg) {
            mNotifyMsg = msg;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onRtmpVideoStreaming(String msg) {
        }

        @Override
        public void onRtmpAudioStreaming(String msg) {
        }

        @Override
        public void onRtmpStopped(String msg) {
            mNotifyMsg = msg;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onRtmpDisconnected(String msg) {
            mNotifyMsg = msg;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onRtmpOutputFps(final double fps) {
            Log.i(TAG, String.format("Output Fps: %f", fps));
        }
    });

    private SrsMp4Muxer mp4Muxer = new SrsMp4Muxer(new SrsMp4Muxer.EventHandler() {
        @Override
        public void onRecordPause(String msg) {
            mNotifyMsg = msg;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onRecordResume(String msg) {
            mNotifyMsg = msg;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onRecordStarted(String msg) {
            mNotifyMsg = "Recording file: " + msg;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onRecordFinished(String msg) {
            mNotifyMsg = "MP4 file saved: " + msg;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_SHORT).show();
                }
            });
        }
    });

    private SrsEncoder mEncoder = new SrsEncoder(flvMuxer, mp4Muxer);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_live_anchor_ii);
        // response screen rotation event
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);

        // restore data.
        sp = getSharedPreferences("SrsPublisher", MODE_PRIVATE);
//        rtmpUrl = sp.getString("rtmpUrl", rtmpUrl);


        webView = (WebView) findViewById(R.id.webview);
        webView.setBackgroundColor(0);
        WebSettings settings = webView.getSettings();
        settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        settings.setJavaScriptEnabled(true);
        // 设置填充透明度 范围：0-255
        //WebView加载web资源
        String urlString = "http://www.baidu.com";
//        webView.loadUrl("http://blog.sina.com.cn/s/blog_5f98d3100100w135.html");
        webView.loadUrl("http://kldy8.com/live/test");
        //覆盖WebView默认使用第三方或系统默认浏览器打开网页的行为，使网页用WebView打开
        webView.setWebViewClient(new WebViewClient()
        {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url)
            {
                // TODO Auto-generated method stub
                //返回值是true的时候控制去WebView打开，为false调用系统浏览器或第三方浏览器
                view.loadUrl(url);
                return true;
            }
        });


        // initialize url.
        efu = (EditText) findViewById(R.id.url);
        efu.setText(rtmpUrl);


        // for camera, @see https://developer.android.com/reference/android/hardware/Camera.html
//        btnPublish = (Button) findViewById(R.id.publish);
        btnSwitch = (Button) findViewById(R.id.swCam);
        btnRecord = (Button) findViewById(R.id.record);
        mCameraView = (SurfaceView) findViewById(R.id.preview);
        mCameraView.getHolder().addCallback(this);

        btnTalk = (Button) findViewById(R.id.talk);

        adapterData =  new ArrayList<String>();

        msg_list_view = (ListView) findViewById(R.id.msg_list_view);

        msgAdapter = new ArrayAdapter<String>(LiveAnchorActivity.this,
                R.layout.my_item, adapterData);
        msg_list_view.setAdapter(msgAdapter);



        talk_edit = (AutoCompleteTextView) findViewById(R.id.tv_talk);
        talk_edit.setOnEditorActionListener(new TextView.OnEditorActionListener()
        {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
            {
                //当actionId == XX_SEND 或者 XX_DONE时都触发
                //或者event.getKeyCode == ENTER 且 event.getAction == ACTION_DOWN时也触发
                //注意，这是一定要判断event != null。因为在某些输入法上会返回null。
                if (actionId == EditorInfo.IME_ACTION_SEND
                        || actionId == EditorInfo.IME_ACTION_DONE
                        || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode() && KeyEvent.ACTION_DOWN == event.getAction()))
                {
                    //处理事件
                    String message = v.getText().toString();
                    Log.e("TAG",message);
                    sendMeg(message);
                }
                return false;
            }
        });

        hini_send_ly = (LinearLayout) findViewById(R.id.hini_send_ly);

        btnTalk.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                btnSwitch.setVisibility(View.GONE);
                btnTalk.setVisibility(View.GONE);
                hini_send_ly.setVisibility(View.VISIBLE);
                isEditStat = true;
            }
        });

        btnSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mCamera != null && mEncoder != null) {
                    mCamId = (mCamId + 1) % Camera.getNumberOfCameras();
                    stopCamera();
                    mEncoder.swithCameraFace();
                    startCamera();
                }
            }
        });

        btnRecord.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)

            {
                if (btnRecord.getText().toString().contentEquals("record"))
                {
                    try {
                        mp4Muxer.record(new File(recPath));
                    } catch (IOException e) {
                        Log.e(TAG, "start MP4 muxer failed.");
                        e.printStackTrace();
                    }
                    btnRecord.setText("pause");
                }
                else if (btnRecord.getText().toString().contentEquals("pause"))
                {
                    mp4Muxer.pause();
                    btnRecord.setText("resume");
                }
                else if (btnRecord.getText().toString().contentEquals("resume"))
                {
                    mp4Muxer.resume();
                    btnRecord.setText("pause");
                }
            }
        });

        makesure = (Button) findViewById(R.id.makesure);
        makesure.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                finish();
            }
        });

        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {
                mNotifyMsg = ex.getMessage();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), mNotifyMsg, Toast.LENGTH_LONG).show();
                        stopEncoder();
                        flvMuxer.stop();
                        mp4Muxer.stop();
//                        btnPublish.setText("publish");
                        btnRecord.setText("record");
                    }
                });
            }
        });

        dome();



        talk_edit = (AutoCompleteTextView) findViewById(R.id.tv_talk);
        talk_edit.setOnEditorActionListener(new TextView.OnEditorActionListener()
        {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
            {
                String token = null;
                if(token == null)
                {
                    Intent intent = new Intent();
//                    intent.setClass(LiveAnchorActivity.this, LoginActivity.class);
                    startActivity(intent);
                }
                //当actionId == XX_SEND 或者 XX_DONE时都触发
                //或者event.getKeyCode == ENTER 且 event.getAction == ACTION_DOWN时也触发
                //注意，这是一定要判断event != null。因为在某些输入法上会返回null。
                if (actionId == EditorInfo.IME_ACTION_SEND
                        || actionId == EditorInfo.IME_ACTION_DONE
                        || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode() && KeyEvent.ACTION_DOWN == event.getAction()))
                {

                    //处理事件
                    String message = v.getText().toString();
                    Log.e("TAG", message);
                    sendMeg(message);
                    talk_edit.setText("");
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(talk_edit.getWindowToken(), 0);
                    talk_edit.setFocusable(false);

                }
                return true;
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void startCamera() {
        if (mCamera != null) {
            Log.d(TAG, "start camera, already started. return");
            return;
        }
        if (mCamId > (Camera.getNumberOfCameras() - 1) || mCamId < 0) {
            Log.e(TAG, "####### start camera failed, inviald params, camera No.="+ mCamId);
            return;
        }

        mCamera = Camera.open(mCamId);
        Camera.Parameters params = mCamera.getParameters();
		/* preview size  */
        Camera.Size size = mCamera.new Size(SrsEncoder.VPREV_WIDTH, SrsEncoder.VPREV_HEIGHT);
        if (!params.getSupportedPreviewSizes().contains(size)) {
            Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(),
                    new IllegalArgumentException(String.format("Unsupported preview size %dx%d", size.width, size.height)));
        }

        /* picture size  */
        if (!params.getSupportedPictureSizes().contains(size)) {
            Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(),
                    new IllegalArgumentException(String.format("Unsupported picture size %dx%d", size.width, size.height)));
        }

        /***** set parameters *****/
        //params.set("orientation", "portrait");
        //params.set("orientation", "landscape");
        //params.setRotation(90);
        params.setPictureSize(SrsEncoder.VPREV_WIDTH, SrsEncoder.VPREV_HEIGHT);
        params.setPreviewSize(SrsEncoder.VPREV_WIDTH, SrsEncoder.VPREV_HEIGHT);
        int[] range = findClosestFpsRange(SrsEncoder.VFPS, params.getSupportedPreviewFpsRange());
        params.setPreviewFpsRange(range[0], range[1]);
        params.setPreviewFormat(SrsEncoder.VFORMAT);
        params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
        params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
        mCamera.setParameters(params);

        mCamera.setDisplayOrientation(mPreviewRotation);

        mCamera.addCallbackBuffer(mYuvFrameBuffer);
        mCamera.setPreviewCallbackWithBuffer(this);
        try {
            mCamera.setPreviewDisplay(mCameraView.getHolder());
        } catch (IOException e) {
            e.printStackTrace();
        }
        mCamera.startPreview();
    }

    private void stopCamera() {
        if (mCamera != null) {
            // need to SET NULL CB before stop preview!!!
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    private void onGetYuvFrame(byte[] data) {
        mEncoder.onGetYuvFrame(data);
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera c) {
        onGetYuvFrame(data);
        c.addCallbackBuffer(mYuvFrameBuffer);
    }

    private void onGetPcmFrame(byte[] pcmBuffer, int size) {
        mEncoder.onGetPcmFrame(pcmBuffer, size);
    }

    private void startAudio() {
        if (mic != null) {
            return;
        }

        int bufferSize = 2 * AudioRecord.getMinBufferSize(SrsEncoder.ASAMPLERATE, SrsEncoder.ACHANNEL, SrsEncoder.AFORMAT);
        mic = new AudioRecord(MediaRecorder.AudioSource.MIC, SrsEncoder.ASAMPLERATE, SrsEncoder.ACHANNEL, SrsEncoder.AFORMAT, bufferSize);
        mic.startRecording();

        byte pcmBuffer[] = new byte[4096];
        while (aloop && !Thread.interrupted()) {
            int size = mic.read(pcmBuffer, 0, pcmBuffer.length);
            if (size <= 0) {
                Log.e(TAG, "***** audio ignored, no data to read.");
                break;
            }
            onGetPcmFrame(pcmBuffer, size);
        }
    }

    private void stopAudio() {
        aloop = false;
        if (aworker != null) {
            Log.i(TAG, "stop audio worker thread");
            aworker.interrupt();
            try {
                aworker.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
                aworker.interrupt();
            }
            aworker = null;
        }

        if (mic != null) {
            mic.setRecordPositionUpdateListener(null);
            mic.stop();
            mic.release();
            mic = null;
        }
    }

    private void startEncoder() {
        int ret = mEncoder.start();
        if (ret < 0) {
            return;
        }

        startCamera();

        aworker = new Thread(new Runnable() {
            @Override
            public void run() {
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
                startAudio();
            }
        });
        aloop = true;
        aworker.start();
    }

    private void stopEncoder() {
        stopAudio();
        stopCamera();
        mEncoder.stop();
    }

    private static int[] findClosestFpsRange(int expectedFps, List<int[]> fpsRanges) {
        expectedFps *= 1000;
        int[] closestRange = fpsRanges.get(0);
        int measure = Math.abs(closestRange[0] - expectedFps) + Math.abs(closestRange[1] - expectedFps);
        for (int[] range : fpsRanges) {
            if (range[0] <= expectedFps && range[1] >= expectedFps) {
                int curMeasure = Math.abs(range[0] - expectedFps) + Math.abs(range[1] - expectedFps);
                if (curMeasure < measure) {
                    closestRange = range;
                    measure = curMeasure;
                }
            }
        }
        return closestRange;
    }

    private static String getRandomAlphaString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    private static String getRandomAlphaDigitString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.d(TAG, "surfaceChanged");
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        Log.d(TAG, "surfaceCreated");
        if (mCamera != null) {
            try {
                mCamera.setPreviewDisplay(mCameraView.getHolder());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        Log.d(TAG, "surfaceDestroyed");
    }

    @Override
    protected void onResume() {
        super.onResume();
        final Button btn = (Button) findViewById(R.id.publish);
        btn.setEnabled(true);
        mp4Muxer.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mp4Muxer.pause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopEncoder();
        flvMuxer.stop();
        mp4Muxer.stop();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            mPreviewRotation = 90;
        }
        else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            mPreviewRotation = 0;
        }
        stopEncoder();
        mp4Muxer.stop();
        btnRecord.setText("record");
        mEncoder.setScreenOrientation(newConfig.orientation);
        if (publish == true) {
            startEncoder();
        }
    }


    public void dome()
    {
        {
            if (publish == false) {
                rtmpUrl = efu.getText().toString();
                Log.i(TAG, String.format("RTMP URL changed to %s", rtmpUrl));
                SharedPreferences.Editor editor = sp.edit();
                editor.putString("rtmpUrl", rtmpUrl);
                editor.commit();

                try {
                    flvMuxer.start(rtmpUrl);
                } catch (IOException e) {
                    Log.e(TAG, "start FLV muxer failed.");
                    e.printStackTrace();
                    return;
                }
                flvMuxer.setVideoResolution(mEncoder.VOUT_WIDTH, mEncoder.VOUT_HEIGHT);

                startEncoder();
                publish = true;
            } else if (publish == true) {
                stopEncoder();
                flvMuxer.stop();
                mp4Muxer.stop();
                publish = false;
                btnRecord.setText("record");
            }
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)
        {
            if (isEditStat == false){
            showAlertDialog();}
            else
            {
                btnSwitch.setVisibility(View.VISIBLE);
                btnTalk.setVisibility(View.VISIBLE);
                hini_send_ly.setVisibility(View.GONE);
                isEditStat = false;
            }
        }
            return true;
    }

    private void showAlertDialog()
    {
        String basicDialog = "TAG1";
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        Fragment fragment = getFragmentManager().findFragmentByTag(basicDialog);
        if (null != fragment) {
            ft.remove(fragment);
        }

        AlertDialogFragment dialogFragment = new AlertDialogFragment();
        dialogFragment.show(ft, basicDialog);
    }

    @Override
    public void doPositiveClick()
    {
//        showToast("确定按钮");
        final RelativeLayout finish_relative = (RelativeLayout) findViewById(R.id.finish_relative);
        finish_relative.setVisibility(View.VISIBLE);
    }

    @Override
    public void doNegativeClick()
    {
//        showToast("取消按钮");
    }

    public void sendMeg(String meg)
    {
        addArray(meg);
    }


    public void addArray(String addSth)
    {
            adapterData.add(addSth);
            msgAdapter.notifyDataSetChanged();
    }
}
